package tech.eyao.hs60x.serviceImpl;

import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import tech.eyao.hs60x.co.ShakeCo;
import tech.eyao.hs60x.common.ConstantsKey;
import tech.eyao.hs60x.dao.AccountDao;
import tech.eyao.hs60x.dao.ApprovalDao;
import tech.eyao.hs60x.dto.BaseResult;
import tech.eyao.hs60x.dto.ShakeDTO;
import tech.eyao.hs60x.enums.AccountType;
import tech.eyao.hs60x.enums.ApprovalStatus;
import tech.eyao.hs60x.model.domain.AccountDO;
import tech.eyao.hs60x.model.domain.ApprovalDO;
import tech.eyao.hs60x.redis.template.ShakeCoRedisTemplate;
import tech.eyao.hs60x.service.ShakeService;
import tech.eyao.hs60x.task.ShakeTask;
import tech.eyao.hs60x.utils.DateUtil;
import tech.eyao.hs60x.utils.ThreadUtil;

/**
 * @author hejian
 * @date 2018年1月24日 上午11:25:15
 */
@Service
public class ShakeServiceImpl implements ShakeService {
	private static final Logger logger = LoggerFactory.getLogger(ShakeServiceImpl.class);
	
	@Autowired
	private ShakeCoRedisTemplate shakeCoRedisTemplate;
	@Autowired
	private ApprovalDao approvalDao;
	@Autowired
	private AccountDao accountDao;
	@Autowired
	private StringRedisTemplate template;
	
	@SuppressWarnings("unchecked")
	@Override
	public List<ShakeDTO> shake(long accountId, double longitude, double latitude) {
		if(longitude <= 0 || latitude <= 0) {
			return null;
		}
		
		try {
			Set<ShakeCo> set = null;
			long score = System.currentTimeMillis();
			ShakeCo shakeCo = new ShakeCo(longitude, latitude, accountId);
			try {
				shakeCoRedisTemplate.opsForZSet().add(ConstantsKey.getShakeKey(), shakeCo, score);
				double startScore = DateUtil.getTimestamp(score,-30);
				double endScore = DateUtil.getTimestamp(score,30);
				set = shakeCoRedisTemplate.opsForZSet().rangeByScore(ConstantsKey.getShakeKey(), startScore, endScore);
			} catch (Exception e) {
				e.printStackTrace();
			}
			
			if(!CollectionUtils.isEmpty(set)) {
				Future<List<ShakeDTO>> future = (Future<List<ShakeDTO>>) ThreadUtil.submit(new ShakeTask(accountId, set, longitude, latitude));
				try {
					return future.get();
				} catch (InterruptedException | ExecutionException e) {
					e.printStackTrace();
				}
			}
		} catch (Exception e) {
			logger.error("[ShakeService shake error.]", e);
		}
		return null;
	}

	@Override
	public BaseResult addFriend(long watchId, long friendWatchId, String friendName) {
		AccountDO watchDo = accountDao.selectByPrimaryKey(watchId);
		if(null == watchDo) {
			return BaseResult.isBussinessFail("登录账户不存在");
		}
		
		// 是否有管理账户
		long watchAdmin = Long.parseLong(template.opsForValue().get(ConstantsKey.getWatchAdminKey(watchId)));
		long friendWatchAmin = Long.parseLong(template.opsForValue().get(ConstantsKey.getWatchAdminKey(friendWatchId)));
		if(watchAdmin <= 0 || friendWatchAmin <= 0) {
			return BaseResult.isBussinessFail("双方账户必须绑定管理员");
		}
		boolean result = Boolean.TRUE;
		// 双向好友
		ApprovalDO approvalDO = new ApprovalDO();
		approvalDO.setFriendId(friendWatchId);
		approvalDO.setFriendNickName(friendName);
		approvalDO.setOwnId(watchAdmin); //审批人
		approvalDO.setStatus(ApprovalStatus.NO.getValue());
		approvalDO.setWatchId(watchId);
		approvalDO.setType(AccountType.WATCH.getValue());
		// 是否已经存在
		if(!approvalDao.isHas(watchId, friendWatchId, ApprovalStatus.NO.getValue())) {
			result = approvalDao.insert(approvalDO);
			if(!result) logger.warn("[ShareService addFriend fail] watchId={},friendId={},friendName={}",watchId,friendWatchId,friendName);
		}
		
		ApprovalDO otherWatch = new ApprovalDO();
		otherWatch.setFriendId(watchId);
		otherWatch.setFriendNickName(watchDo.getNickName());
		otherWatch.setOwnId(friendWatchAmin); //审批人
		otherWatch.setStatus(ApprovalStatus.NO.getValue());
		otherWatch.setWatchId(friendWatchId);
		otherWatch.setType(AccountType.WATCH.getValue());
		if(!approvalDao.isHas(friendWatchId, watchId, ApprovalStatus.NO.getValue())) {
			result = approvalDao.insert(otherWatch);
			if(!result) logger.warn("[ShareService addFriend other watch fail] watchId={},friendId={},friendName={}",watchId,friendWatchId,friendName);
		}
		return BaseResult.isSuccess();
	}
}
